package cn.zhqr.core.service;

import cn.zhqr.common.bean.response.ErrorCode;
import cn.zhqr.common.bean.response.OutResponse;
import cn.zhqr.common.config.GlobalConstants;
import cn.zhqr.common.utils.DateUtils;
import cn.zhqr.common.util.number.SnowflakeIdWorker;
import cn.zhqr.common.util.validate.ParamCheck;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * 用户洗车卡业务
 */
public class UserCardService {
    public static final UserCardService instance = new UserCardService();
    public static final Logger logger = Logger.getLogger(UserCardService.class);

    /**
     * 购买洗车卡
     * 需在事务中运行！！！
     * @param payOrder
     * @return
     */
    public OutResponse getCardFromBuy(PayOrder payOrder){
        return getCard(payOrder.getUserId(),payOrder.getGoodsId(),UserWashCard.GET_FROM_BUY,null,payOrder.getOrderNo());
    }

    /**
     * 运营商后台赠卡
     * @param userId
     * @param cardId
     * @param balance
     * @return
     */
    public OutResponse getCardFromGive(Long userId, Long cardId, BigDecimal balance) {
        return getCard(userId,cardId,UserWashCard.GET_FROM_GIVE,balance,null);
    }

    /**
     * 兑换码兑换卡
     * @param userId
     * @param washCard
     * @return
     */
    public OutResponse getCardFromRedeemCode(Long userId, WashCard washCard) {
        return getCard(userId,washCard,UserWashCard.GET_FROM_REDEEM_CODE,null,null);
    }

    /**
     * 免费获取卡
     * @param userId
     * @param washCard
     * @return
     */
    public OutResponse getCardForFree(Long userId, WashCard washCard) {
        return getCard(userId,washCard,UserWashCard.GET_FROM_FREE,null,null);
    }

    /**
     * 从运营活动中获取卡
     * @param userId
     * @param washCard
     * @param activityId
     * @return
     */
    public OutResponse getCardFromActivity(Long userId, WashCard washCard, Long activityId) {
        return getCard(userId,washCard,activityId.intValue(),null,null);
    }

    public OutResponse getCardFromActivity(Long userId, Long cardId, Long activityId) {
        return getCard(userId,cardId,activityId.intValue(),null,null);
    }

    public OutResponse getCard(Long userId, WashCard washCard, Integer getFrom) {
        return getCard(userId,washCard,getFrom,null,null);
    }

    public OutResponse getCard(Long userId, Long cardId, Integer getFrom) {
        return getCard(userId,cardId,getFrom,null,null);
    }

    public OutResponse getCard(Long userId, Long cardId, Integer getFrom, BigDecimal balance, BigInteger orderNo) {
        if (userId == null) {
            return OutResponse.buildError(ErrorCode.INVALID_PARAM, "用户id不能为空");
        }
        if (cardId == null) {
            return OutResponse.buildError(ErrorCode.INVALID_PARAM, "洗车卡id不能为空");
        }
        if (getFrom == null) {
            return OutResponse.buildError(ErrorCode.INVALID_PARAM, "getFrom参数不能为空");
        }
        WashCard washCard = WashCard.dao.findById(cardId);
        return getCard(userId,washCard,getFrom,balance,orderNo);
    }

    public OutResponse getCard(Long userId, WashCard washCard, Integer getFrom, BigDecimal balance, BigInteger orderNo){
        if(userId == null){
            return OutResponse.buildError(ErrorCode.INVALID_PARAM,"用户id不能为空");
        }
        if(getFrom == null){
            return OutResponse.buildError(ErrorCode.INVALID_PARAM,"getFrom参数不能为空");
        }
        if(washCard == null){
            return OutResponse.buildError(ErrorCode.INVALID_PARAM,"洗车卡不能为空");
        }

        UserWashCard userWashCard = new UserWashCard();
        userWashCard.setUserid(userId);
        userWashCard.setGetFrom(getFrom);
        if(orderNo != null){
            userWashCard.setPayOrderNo(orderNo);
        }
        if(balance != null){
            if(washCard.getType()==WashCard.TYPE_VALUE && balance.compareTo(washCard.getAmount())>0){
                return OutResponse.buildError(ErrorCode.INVALID_PARAM,"赠送金额不能超过洗车卡面值");
            }
            balance = balance.setScale(2, GlobalConstants.DEFAULT_ROUNDING_MODE);
        }else{
            balance = washCard.getAmount();
        }
        userWashCard.setBalance(balance);
        userWashCard.setCardId(washCard.getId());
        userWashCard.setCardType(washCard.getType());
        userWashCard.setCardName(washCard.getName());
        userWashCard.setMaxTimes(washCard.getMaxTimes());
        userWashCard.setUseTimes(0);
        userWashCard.setStatus(UserWashCard.STATUS_ACTIVE);
        userWashCard.setUsableStartTime(washCard.getUsableStartTime());
        userWashCard.setUsableEndTime(washCard.getUsableEndTime());
        Calendar calendar = Calendar.getInstance();
        userWashCard.setCreateTime(calendar.getTime());
        //激活卡
        userWashCard.setActiveTime(calendar.getTime());
        calendar.add(Calendar.DAY_OF_YEAR,washCard.getDays());
        calendar.set(Calendar.HOUR,23);
        calendar.set(Calendar.MINUTE,59);
        calendar.set(Calendar.SECOND,59);
        calendar.set(Calendar.MILLISECOND,999);
        userWashCard.setExpireTime(calendar.getTime());

        userWashCard.setEffect(washCard.getEffect());
        userWashCard.setSellerId(washCard.getSellerId());
        userWashCard.save();

        WashCardStock.dao.decreaseStock(washCard.getId(), 1);

        if(getFrom == UserWashCard.GET_FROM_BUY){
            WashCardStock.dao.increaseSales(washCard.getId(), 1);
        }else if(getFrom == UserWashCard.GET_FROM_REDEEM_CODE){
            WashCardStock.dao.increaseRedeem(washCard.getId(), 1);
        }else{
            WashCardStock.dao.increaseGive(washCard.getId(), 1);
        }

        return OutResponse.buildSuccess();
    }


    /**
     * 检查洗车卡是否可用
     * @param userWashCard
     * @param user
     * @param station
     * @return
     */
    public OutResponse checkUserWashCard(UserWashCard userWashCard,User user,Station station){
        if(userWashCard==null){
            return OutResponse.buildError(ErrorCode.NO_WASH_CARD);
        }
        if(user ==null){
            return OutResponse.buildError(ErrorCode.NOT_LOGIN);
        }
        if(station == null){
            return OutResponse.buildError(ErrorCode.DEVICE_UNBIND);
        }
        if(!userWashCard.getUserid().equals(user.getId())){
            return OutResponse.buildError(ErrorCode.NO_PERMISSION_WASH_CARD,"您无权使用该卡，请先购买");
        }

        LocalTime cardUsableStartTime = DateUtils.parseLocalTime(userWashCard.getUsableStartTime());
        LocalTime cardUsableEndTime = DateUtils.parseLocalTime(userWashCard.getUsableEndTime());
        LocalTime now = LocalTime.now();

        if(!DateUtils.isTimeInRange(now,cardUsableStartTime,cardUsableEndTime)){
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
            return OutResponse.buildError(ErrorCode.DEVICE_SUSPEND,"当前时段该卡不可用，可用时段："+cardUsableStartTime.format(formatter)+"~"+cardUsableEndTime.format(formatter));
        }

        WashCard washCard = WashCard.dao.findById(userWashCard.getCardId());
        ParamCheck.isNotNull(washCard,"该洗车卡不存在");

        if(washCard.getEffect()==WashCard.EFFECT_ALL && !userWashCard.getSellerId().equals(station.getOwnerId())){
            return OutResponse.buildError(ErrorCode.NO_PERMISSION_WASH_CARD,"该卡不能在本站使用");
        }else if(washCard.getEffect()==WashCard.EFFECT_SPECIFIED){
            WashCardLinkStation link = WashCardLinkStation.dao.findByStationIdAndCardId(station.getId(),userWashCard.getCardId());
            if(link == null){
                return OutResponse.buildError(ErrorCode.NO_PERMISSION_WASH_CARD,"该卡不能在本站使用");
            }
        }

        if(userWashCard.getCardType().equals(WashCard.TYPE_MONTH)){
            long todayFinishedTimes = UserOrder.dao.countTodayFinishedByCardIdAndMinAmount(userWashCard.getId(), GlobalConstants.CARD_ONCE_MIN_AMOUNT);
            if(todayFinishedTimes > 0){
                logger.error("月卡每日限用一次，请使用其他卡："+userWashCard.getId());
                return OutResponse.buildError(ErrorCode.WASH_CARD_TODAY_USED_UP,"月卡每日限用一次，请使用其他卡");
            }
        }

        return checkUserWashCardStatus(userWashCard);
    }


    /**
     * 检查洗车卡状态
     * @param userWashCard
     * @return
     */
    public OutResponse checkUserWashCardStatus(UserWashCard userWashCard){
        if(userWashCard.getExpireTime().getTime()<=Calendar.getInstance().getTime().getTime()){ //已过期
            userWashCard.setStatus(UserWashCard.STATUS_EXPIRED);
            userWashCard.update();
            return OutResponse.buildError(ErrorCode.WASH_CARD_EXPIRED);
        }
        if(userWashCard.getCardType()==WashCard.TYPE_VALUE && userWashCard.getBalance().compareTo(BigDecimal.ZERO)<=0){
            userWashCard.setStatus(UserWashCard.STATUS_USED_UP);
            userWashCard.update();
            return OutResponse.buildError(ErrorCode.WASH_CARD_USED_UP);
        }
        if(userWashCard.getCardType()==WashCard.TYPE_TIMES && userWashCard.getUseTimes()>=userWashCard.getMaxTimes()){
            userWashCard.setStatus(UserWashCard.STATUS_USED_UP);
            userWashCard.update();
            return OutResponse.buildError(ErrorCode.WASH_CARD_USED_UP);
        }
        return OutResponse.buildSuccess();
    }


    /**
     * 使用代金卡
     * @param washOrder
     * @param payAmount
     * @param userWashCard
     * @return
     */
    public BigDecimal useValueWashCard(UserOrder washOrder, BigDecimal payAmount, UserWashCard userWashCard) {
        //锁住洗车卡，防止余额更新出错
        UserWashCard.dao.findAndLockById(userWashCard.getId());


        //金额超过卡内余额,则以卡内余额为准
        if(payAmount.compareTo(userWashCard.getBalance()) > 0){
            payAmount = userWashCard.getBalance();
        }

        //扣除余额
        if(payAmount.compareTo(BigDecimal.ZERO) > 0){
            //更新卡余额
            UserWashCard.dao.increaseBalance(userWashCard.getId(), payAmount.negate());

            //更新后余额
            BigDecimal balance = userWashCard.getBalance().subtract(payAmount);

            SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(1);
            long tradeNo = snowflakeIdWorker.nextId();
            //记录资金明细
            UserTrade trade = new UserTrade();
            trade.setTradeNo(BigInteger.valueOf(tradeNo));
            trade.setOrderNo(washOrder.getOrderNo());
            trade.setUserid(washOrder.getUserId());
            trade.setAgentId(washOrder.getAgentId());
            trade.setTradeType(UserTrade.TYPE_WASH);
            trade.setAmount(payAmount.negate());
            trade.setPayChannel(GlobalConstants.PAY_CHANNEL_WASH_CARD);
            trade.setCardId(userWashCard.getId());
            trade.setBalance(balance);
            trade.setCreateTime(new Date());
            trade.save();
        }
        return payAmount;
    }

    /**
     * 申请退款
     * @param userWashCardId
     * @param refundAmount
     * @param remark
     * @return
     */
    public OutResponse applyRefund(Long userWashCardId, BigDecimal refundAmount, String remark,Long agentId){
        UserWashCard userWashCard = UserWashCard.dao.findById(userWashCardId);
        ParamCheck.isNotNull(userWashCard,"该卡不存在");
        if(userWashCard.getStatus()!=UserWashCard.STATUS_ACTIVE){
            return OutResponse.buildError(ErrorCode.INVALID_PARAM,"该卡已失效，不可再退");
        }
        if(agentId!=null && !userWashCard.getSellerId().equals(agentId)){
            return OutResponse.buildError(ErrorCode.INVALID_PARAM,"无权操作该卡");
        }
        if(userWashCard.getCardType()==WashCard.TYPE_VALUE && refundAmount.compareTo(userWashCard.getBalance())>0){
            return OutResponse.buildError(ErrorCode.INVALID_PARAM,"退款金额不能大于卡内余额");
        }

        BigInteger payOrderNo = userWashCard.getPayOrderNo();

        return PayOrderService.instance.applyRefund(payOrderNo,refundAmount,remark);
    }


    public OutResponse revoke(Long userWashCardId,Long agentId){
        UserWashCard userWashCard = UserWashCard.dao.findById(userWashCardId);
        ParamCheck.isNotNull(userWashCard,"该卡不存在");
        if(userWashCard.getStatus()!=UserWashCard.STATUS_ACTIVE){
            return OutResponse.buildError(ErrorCode.INVALID_PARAM,"该卡已失效，不可再退");
        }
        if(agentId!=null && !userWashCard.getSellerId().equals(agentId)){
            return OutResponse.buildError(ErrorCode.INVALID_PARAM,"无权操作该卡");
        }

        userWashCard.setStatus(UserWashCard.STATUS_CANCEL);
        userWashCard.setExpireTime(new Date());
        userWashCard.update();

        return OutResponse.buildSuccess("撤销成功",null);
    }
}
